﻿using System;
using System.Collections.Generic;
using System.Text;
using MediaCenterCommander.RemoteInterfaces;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace MediaCenterCommander.LocalControl
{
    public static class MediaCenterLocalController
    {
        private static bool s_autoAttemptToConnectToMediaCenter = true;
        private static bool s_useMediaCenterCommanderUserAgentToLaunchMediaCenter = false;

        public static bool AutoAttemptToConnectToMediaCenter
        {
            get { return s_autoAttemptToConnectToMediaCenter; }
            set { s_autoAttemptToConnectToMediaCenter = value; }
        }

        public static bool UseMediaCenterCommanderUserAgentToLaunchMediaCenter
        {
            get { return s_useMediaCenterCommanderUserAgentToLaunchMediaCenter; }
            set { s_useMediaCenterCommanderUserAgentToLaunchMediaCenter = value; }
        }

        private static void LaunchMediaCenterIfNotRunning()
        {
            string expectedMediaCenterExe = System.IO.Path.GetDirectoryName(Environment.SystemDirectory) + @"\ehome\ehshell.exe";

            if (!File.Exists(expectedMediaCenterExe))
            {
                throw new Exception("Media Center not found at " + expectedMediaCenterExe);
            }

            Process[] processList = Process.GetProcessesByName("ehshell");
            if (processList == null || processList.Length == 0)
            {
                if (!UseMediaCenterCommanderUserAgentToLaunchMediaCenter)
                {
                    ProcessStartInfo psi = new ProcessStartInfo();
                    psi.FileName = expectedMediaCenterExe;
                    psi.WindowStyle = ProcessWindowStyle.Maximized;
                    psi.Arguments = "/nostartupanimation";
                    Process.Start(psi);
                }
                else
                {
                    // TODO: Don't hardcode url here.
                    var mccUserAgent = (IMediaCenterCommanderUserAgent)
                        RemotingServices.Connect(typeof(IMediaCenterCommanderUserAgent),
                            "tcp://127.0.0.1:9902/IMediaCenterCommanderUserAgent");

                    mccUserAgent.LaunchMediaCenterIfNotRunning();
                }
            }
        }

        public static void AttemptToConnectToMediaCenter()
        {
            LaunchMediaCenterIfNotRunning();

            // Attempt to wait for Media Center Commander plugin to load.
            bool success = false;

            int attemptsLeft = 20;
            while (attemptsLeft > 0)
            {
                try
                {
                    var mcc = GetMediaCenterController();
                    mcc.GetMediaCenterEnvironmentVersion();
                    Console.WriteLine("Connected to Media Center.");
                    success = true;
                    break;
                }
                catch
                {
                    Console.WriteLine("Connection to Media Center attempt failed.");
                    Thread.Sleep(500);
                }

                attemptsLeft--;
            }

            if (!success)
            {
                throw new Exception("Unable to connect to Media Center.");
            }
        }

        public static void WatchChannel(int channel)
        {
            if (AutoAttemptToConnectToMediaCenter)
                AttemptToConnectToMediaCenter();

            var mcc = GetMediaCenterController();
            mcc.SwitchToLiveTV();  
            mcc.WatchTVChannel(channel);
        }

        public static void StartSlideshow(string path)
        {
            if (AutoAttemptToConnectToMediaCenter)
                AttemptToConnectToMediaCenter();

            var mcc = GetMediaCenterController();
            mcc.StartSlideshow(path);            
        }

        public static string GetMediaCenterEnvironmentVersion()
        {
            if (AutoAttemptToConnectToMediaCenter)
                AttemptToConnectToMediaCenter();

            var mcc = GetMediaCenterController();
            return mcc.GetMediaCenterEnvironmentVersion();
        }

        public static void Play()
        {
            if (AutoAttemptToConnectToMediaCenter)
                AttemptToConnectToMediaCenter();

            var mcc = GetMediaCenterController();
            mcc.Play();
        }

        public static void Pause()
        {
            if (AutoAttemptToConnectToMediaCenter)
                AttemptToConnectToMediaCenter();

            var mcc = GetMediaCenterController();
            mcc.Pause();
        }

        public static void Stop()
        {
            if (AutoAttemptToConnectToMediaCenter)
                AttemptToConnectToMediaCenter();

            var mcc = GetMediaCenterController();
            mcc.Stop();
        }

        public static void SkipForward()
        {
            if (AutoAttemptToConnectToMediaCenter)
                AttemptToConnectToMediaCenter();

            var mcc = GetMediaCenterController();
            mcc.SkipForward();
        }

        public static void SkipBack()
        {
            if (AutoAttemptToConnectToMediaCenter)
                AttemptToConnectToMediaCenter();

            var mcc = GetMediaCenterController();
            mcc.SkipBack();
        }

        public static string GetMediaMetadata()
        {
            if (AutoAttemptToConnectToMediaCenter)
                AttemptToConnectToMediaCenter();

            var mcc = GetMediaCenterController();
            return mcc.GetMediaMetadata();
        }



        public static void RegisterStandardChannels()
        {
            IDictionary props = new Hashtable();            
            TcpClientChannel tcpChannel = new TcpClientChannel(props, null);
            ChannelServices.RegisterChannel(tcpChannel, false);
        }

        private static IMediaCenterController GetMediaCenterController()
        {
            string uri = null;

            using (var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\MediaCenterCommander"))
            {
                if (key != null)
                {
                    uri = key.GetValue("IMediaCenterController") as string;
                }
            }

            if (uri == null)
            {
                // TODO: Allow port to be configured in some other manner.
                uri = "tcp://127.0.0.1:9901/IMediaCenterController";
            }

            var mcc = (IMediaCenterController)RemotingServices.Connect(typeof(IMediaCenterController), uri);
            return mcc;
        }
        
    }
}
